namespace ETestIT.Tests.Data.SetUpDb
{
    using System.Data;
    using System.Data.SqlClient;
    using System.IO;
    using ETestIT.Core;
    using ETestIT.Data.NHibernateMaps;
    using FluentNHibernate.Cfg;
    using FluentNHibernate.Cfg.Db;
    using global::Tests;
    using NHibernate.Cfg;
    using NHibernate.Tool.hbm2ddl;
    using NUnit.Framework;
    using SharpArch.Data.NHibernate;
    using SharpArch.Testing.NHibernate;

    [TestFixture]
    public class ApplicationDbSetUpWithPorductionAndTestingData
    {
        readonly string[] mappingAssemblies = RepositoryTestsHelper.GetMappingAssemblies();
    const string ConfigurationFile = "../../../../src/ETestIT.Web/NHibernate.config";

        private string GetDataBaseNameFromConnectionString(string theConfigConnStr)
        {
            return theConfigConnStr
                .Split(';')[1]
                .Split('=')[1];
        }

        private string PrepareMasterConnStr(string theConfigConnStr)
        {
            var userDbName = GetDataBaseNameFromConnectionString(theConfigConnStr);
            return theConfigConnStr.Replace(userDbName, "master");
        }

        [TestFixtureSetUp]
        public void SetUpFixture()
        {
            ServiceLocatorInitializer.Init();
        }

        private void BuildDbSchemaFromDomainMetadata()
        {
            var webAppConnectionStr = new Configuration()
                .Configure(ConfigurationFile)
                .Properties["connection.connection_string"];

            var originalDbName = GetDataBaseNameFromConnectionString(webAppConnectionStr);
            var masterConnString = PrepareMasterConnStr(webAppConnectionStr);

            using(var connection = new SqlConnection(masterConnString))
            {
                using (IDbCommand command = connection.CreateCommand())
                {
                    connection.Open();

                    command.CommandText =
                        @"IF EXISTS(SELECT name FROM master..sysdatabases WHERE name = N'@DB_NAME')
	                        BEGIN
	                           ALTER DATABASE @DB_NAME SET SINGLE_USER with ROLLBACK IMMEDIATE;
	                           DROP DATABASE @DB_NAME; 
	                        END
                        CREATE DATABASE @DB_NAME;"
                        .Replace("@DB_NAME", originalDbName);
                    
                    command.ExecuteNonQuery();
                }
                
                connection.ChangeDatabase(originalDbName);

                var configuration = NHibernateSession.Init(
                        new SimpleSessionStorage(), 
                        mappingAssemblies,
                        new AutoPersistenceModelGenerator().Generate(),
                        ConfigurationFile
                    );
                new SchemaExport(configuration).Create(false, true);
            }
        }

        [Test, Ignore("Run this test only if you want to recreate database ICMS.SC with Production Data")]
        public void BuildSchemaAndDataForProduction()
        {
            BuildDbSchemaFromDomainMetadata();

            new ProductionBuilder().Build();
        }

        [Test, Ignore("Run this test only if you want to recreate database ICMS.SC with Testing Data")]
        public void BuildSchemaAndDataForTesting()
        {
            BuildDbSchemaFromDomainMetadata();

            new ProductionBuilder().Build();
            new TestingBuilder().Build();
        }

        [Test, Ignore("Run this test only if you want to see mappings")]
        public void ShouldExportMappings()
        {
            const string mappingPath = @"mappings";

            if (!Directory.Exists(mappingPath))
                Directory.CreateDirectory(mappingPath);

            var sessionFactory = Fluently.Configure()
                .Database(SQLiteConfiguration.Standard.InMemory)
                .Mappings(m =>
                              {
                                  m.FluentMappings
                                      .AddFromAssemblyOf<User>()
                                      .ExportTo(mappingPath);

                                  m.AutoMappings
                                      .Add(new AutoPersistenceModelGenerator().Generate())
                                      .ExportTo(mappingPath);
                              }).BuildSessionFactory();
        }
    }
}